package join

import (
	"codeup.aliyun.com/lsxd/zltx/adapter/utils/join/filter"
	"codeup.aliyun.com/lsxd/zltx/adapter/utils/sortx/dict"
)

// SortGenFunc 排序函数
type SortGenFunc func(kvs []dict.KeyValue, filter SignFilterFunc, sep string, skipFields []string, valueEncoder dict.ValueEncoder) string

// WrapFunc 包裹函数，用于对签名字符串进行包裹，如加appkey等
type WrapFunc func(str string, warp string) string

// SignFunc 签名函数
type SignFunc func(data string) string

// VerifySignFunc 验证签名函数
type VerifySignFunc func(data, signed string) (bool, error)

// Option 排序选项
type Option func(*options)

// SignFilterFunc 过滤处理函数,true过滤，false不过滤
type SignFilterFunc func(key string, value any) bool

// SortedDict 排好序的键值对
func SortedDict(dict *dict.Dict) Option {
	return func(o *options) {
		o.sortedKvs = dict.List()
	}
}

// SignFilterEmpty 这是一个过时函数
//
// Deprecated: 请使用 SignFilter(filter.FilterZeroValue) 替代。
func SignFilterEmpty(filterEmpty bool) Option {
	return SignFilter(filter.FilterZeroValue)
}

// SignFilter 过滤处理函数空值
func SignFilter(filter SignFilterFunc) Option {
	return func(o *options) {
		o.filter = filter
	}
}

// SignSep 设置拼接符
func SignSep(sep string) Option {
	return func(o *options) {
		o.sep = sep
	}
}

// SignSkipFields 跳过字段
func SignSkipFields(skipFields ...string) Option {
	return func(o *options) {
		o.skipFields = append(o.skipFields, skipFields...)
	}
}

// SignSortGenFunc 设置排序函数
func SignSortGenFunc(sortGenFunc SortGenFunc) Option {
	return func(o *options) {
		o.sortGenFunc = sortGenFunc
	}
}

// SignWrap 设置包裹函数
func SignWrap(wrapFunc WrapFunc, warp string) Option {
	return func(o *options) {
		o.wrapFunc = wrapFunc
		o.signWarp = warp
	}
}

// SignValueEncoder 设置值编码器
func SignValueEncoder(valueEncoder dict.ValueEncoder) Option {
	return func(o *options) {
		o.valueEncoder = valueEncoder
	}
}

// options Builder选项
type options struct {
	// 排好顺序的参数
	sortedKvs []dict.KeyValue

	// 签名包装字符串
	signWarp string
	// 签名过滤空值
	filter SignFilterFunc
	// 拼接符
	sep string
	// 签名跳过字段
	skipFields []string
	// 排序函数
	sortGenFunc SortGenFunc
	// 包裹函数
	wrapFunc WrapFunc
	// valueEncoder 值编码器
	valueEncoder dict.ValueEncoder
}

func defaultOptions() *options {
	return &options{
		sep:        "&",
		skipFields: make([]string, 0),
	}
}

// SignStr 生成签名字符串
func SignStr(opts ...Option) string {
	opt := defaultOptions()
	for _, o := range opts {
		o(opt)
	}

	var signStr string
	// 若未设置排序键值对，则不生成签名字符串
	if len(opt.sortedKvs) > 0 {

		// 1、利用排好序的键值对生成签名字符串
		signStr = opt.sortGenFunc(opt.sortedKvs, opt.filter, opt.sep, opt.skipFields, opt.valueEncoder)

		// 2、包裹签名字符串
		if opt.wrapFunc != nil {
			signStr = opt.wrapFunc(signStr, opt.signWarp)
		}
		return signStr
	}

	return signStr
}
